#ifndef __MMATHLINK__
#define __MMATHLINK__

@class MEnvironment, SocketObserver;

typedef enum {
	eExprTypeString,
	eExprTypeSymbol,
	eExprTypeInteger,
	eExprTypeReal,
	eExprTypeFunction
} MExprType;

@interface MMathLink : NSObject
{
@protected
	MEnvironment* _env;
	void* _link;
	BOOL _close;
	
	SocketObserver* _linkObserver;
	SocketObserver* _messageObserver;
	id _delegate;
	void* _oldMessageHandler;
@public // not really public
	int _messagePipe[2];
}

+ (id) link;
+ (id) linkWithArgs: (NSString*) args;
+ (id) linkWithArgv: (NSArray*) argv;
+ (id) linkWithEnvironment: (MEnvironment*) env;
+ (id) linkWithEnvironment: (MEnvironment*) env args: (NSString*) args;
+ (id) linkWithEnvironment: (MEnvironment*) env argv: (NSArray*) argv;
- (id) initWithEnvironment: (MEnvironment*) env link: (void* /*MLINK*/) link close: (BOOL) close;
- (void) dealloc;

- (void* /*MLINK*/) link;
- (BOOL) connect;
- (NSString*) name;
- (void) setName: (NSString*) name;
- (int) selectFileDescriptor;
- (BOOL) transferToLink: (MMathLink*) theLink;

@end

@interface MMathLink (MMathLinkPacketMethods)

// what is the next packet on the link
- (unsigned long) nextPacket;

// skip the remainder of the current packet and move on
- (BOOL) newPacket;

//
- (BOOL) endPacket;

- (BOOL) handlePacket;

@end

@interface MMathLink (MMathLinkGetterMethods)

- (BOOL) isReady;
- (MExprType) type;
- (NSString*) string;
- (NSString*) symbol;
- (NSData*) data;
- (NSNumber*) number;
- (int) integer;
- (double) real;
- (int) functionLength;
- (int) expressionsToGet;

@end

@interface MMathLink (MMathLinkPutterMethods)

- (BOOL) putString: (NSString*) string;
- (BOOL) putSymbol: (NSString*) symbol;
- (BOOL) putData: (NSData*) data;
- (BOOL) putNumber: (NSNumber*) number;
- (BOOL) putInteger: (int) integer;
- (BOOL) putReal: (double) real;
- (BOOL) putFunctionWithLength: (int) length;
- (BOOL) putFunction: (NSString*) name length: (int) length;
- (BOOL) flush;

@end

@interface MMathLink (MMathLinkErrorMethods)

- (long) error;
- (BOOL) setError: (long) error;
- (BOOL) clearError;
- (NSString*) errorMessage;
- (void) raiseError;

@end

@interface MMathLink (MMathLinkDelegateMethods)

- (id) delegate;
- (void) setDelegate: (id) delegate;
- (CFRunLoopRef) runLoop;
- (void) setRunLoop: (CFRunLoopRef) runLoop;

@end

@interface NSObject (MMathLinkDelegate)

- (void) handlePacket: (int) packet link: (MMathLink*) link;
- (void) handleMessage: (int) message link: (MMathLink*) link;

@end

@interface NSNumber (MMathLinkAdditions)

- (BOOL) isRealNumber;

@end

#endif /* __MMATHLINK__ */
